// MainQwidget.hpp
// Created by Limou on 24-8-12.
// 描述了聊天软件的桌面界面, 并且设计的是懒汉的单例对象

#ifndef FRONTEND_MAINQWIDGET_HPP
#define FRONTEND_MAINQWIDGET_HPP

#include <QWidget>
#include <QSize>
#include <QLineEdit>
#include <QGraphicsBlurEffect>
#include <QEvent>
#include <QMouseEvent>
#include "common/Common.hpp"
#include "model/Model.hpp"
#include "window/Window.hpp"

namespace chat_system {
    // >>> class MainQWidget begin: 主界面类 >>>
    class MainQWidget : public QWidget {
    Q_OBJECT

    private:
        // 部件
        window::WindowLeft* windowLeft_; // 窗口左侧
        window::WindowMiddle* windowMiddle_; // 窗口中间
        window::WindowRight* windowRight_; // 窗口右侧
        // 布局
        QHBoxLayout* hLayoutOfSelf_;
        // 数据
        std::vector<model::ChatSessionModel> historySessionListOfUser_; // 存储历史会话列表(一份缓存, 不一定是最新的)
        std::vector<model::UserModel> haveFriendListOfUser_; // 存储已有好友列表(一份缓存, 不一定是最新的)
        std::vector<model::UserModel> addFriendListOfUser_; // 存储添加好友列表(一份缓存, 不一定是最新的)
        inline static MainQWidget* instance_ = nullptr; // 单例对象

    public:
        // 获取单例指针方法
        static MainQWidget* getInstance() {
            TODO("可以写成单例线程安全的代码, 可能有些许过度设计");
            if (instance_ == nullptr) {
                instance_ = new MainQWidget();
            }
            return instance_;
        }

        // 销毁单例对象方法
        static void delInstance() {
            TODO("可以写成单例线程安全的代码, 可能有些许过度设计");
            if(instance_ != nullptr) {
                delete instance_ ;
                instance_ = nullptr;
            }
        }

        // 禁用拷贝构造方法
        MainQWidget(MainQWidget& other) = delete;

        // 禁用赋值重载方法
        MainQWidget& operator=(const MainQWidget& other) = delete;

    private:
        // 构造方法
        explicit MainQWidget(QWidget* parent = nullptr)
        : QWidget(parent)
        , windowLeft_(new window::WindowLeft(this))
        , windowMiddle_(new window::WindowMiddle(this))
        , windowRight_(new window::WindowRight(this))
        , hLayoutOfSelf_(new QHBoxLayout()) {
            this->setElement();
            this->setElementStaticData();
            this->setElementSize();
            this->setElementStyle();
            this->setElementLayout();
            this->setElementSignalSlot();
            this->setElementShow();
        }

        // 析构方法
        ~MainQWidget() override { delInstance(); }

    private:
        // 设置组件方法
        void setElement() {}

        // 设置组件数据方法
        void setElementStaticData() {
            // 设置软件名称
            this->setWindowTitle("聊天室");

            // 设置软件图标
            QIcon icon(":/window/window_main/logo.png");
            if (icon.isNull()) { common::Tools::getInstance()->getLogger()->warn("缺失软件 logo 图片"); }
            this->setWindowIcon(icon);
        }

        // 设置组件大小方法
        void setElementSize() {}

        // 设置组件风格方法
        void setElementStyle() {}

        // 设置组件布局方法
        void setElementLayout() {
            // 初始化本组件布局
            hLayoutOfSelf_->setSpacing(0);
            hLayoutOfSelf_->setContentsMargins(4, 4, 4, 4);
            this->setLayout(hLayoutOfSelf_);

            // 设置本组件布局
            hLayoutOfSelf_->addWidget(windowLeft_);
            hLayoutOfSelf_->addWidget(windowMiddle_);
            hLayoutOfSelf_->addWidget(windowRight_);
        }

         // 设置组件信号槽方法
        void setElementSignalSlot() {
            // 当 windowLeft_ 发送重加载信号后, windowMiddle_ 重新加载列表
            connect(windowLeft_, &window::WindowLeft::loadWindowMiddle, this, [this](const common::TabType& tabType){
                common::Tools::getInstance()->getLogger()->trace("{0} {1} get loadWindowMiddle signal", __FILE__, __LINE__);
                // 获取 windowMiddle_ 中的 sessionFriendArea_ 并提前做清空
                auto sessionFriendAreaInWindowMiddle = windowMiddle_->getSessionFriendArea();
                sessionFriendAreaInWindowMiddle->clearItem();

                // 如果是会话列表按钮被触发
                if (tabType == common::TabType::SESSION_TAB) {
                    common::Tools::getInstance()->getLogger()->trace("{0} {1} loadWindowMiddle SESSION_TAB", __FILE__, __LINE__);
                    TODO("请求后端查询该用户的历史会话列表记录(就是获取 json 数据)");
                    TODO("可以做时间戳优化");
                    TODO("根据 json 制作列表 historySessionListOfUser_");
                    /*
                    for (auto historySession : historySessionListOfUser_) {
                        sessionFriendAreaInWindowMiddle->addItem(...);
                    }
                    */
                    TODO("这里有测试数据, 等待删除...");
                    for (int i = 0; i < 20; i++) {
                        sessionFriendAreaInWindowMiddle->addItem(
                            common::SessionFriendItemType::SESSION_ITEM_TYPE,
                            QString::number(i),
                            QIcon(":/test/limou.png"),
                            "limou",
                            "Hello, I am limou!"
                        );
                    }
                }
                // 如果是已有好友按钮被触发
                else if (tabType == common::TabType::FRIENDS_TAB) {
                    common::Tools::getInstance()->getLogger()->trace("{0} {1} loadWindowMiddle FRIENDS_TAB", __FILE__, __LINE__);
                    TODO("请求后端查询该用户的已有好友列表记录(就是获取 json 数据)");
                    TODO("可以做时间戳优化");
                    TODO("根据 json 制作列表 haveFriendListOfUser_");
                    /*
                    for (auto haveFriend : haveFriendListOfUser_) {
                        sessionFriendAreaInWindowMiddle->addItem(...);
                    }
                    */
                    TODO("这里有测试数据, 等待删除...");
                    for (int i = 0; i < 20; i++) {
                        sessionFriendAreaInWindowMiddle->addItem(
                            common::SessionFriendItemType::FRIEND_ITEM_TYPE,
                            QString::number(i),
                            QIcon(":/test/yinmou.png"),
                            "yinmou",
                            "Hello, I am yinmou!"
                        );
                    }
                }
                // 如果是添加好友按钮被触发
                else if (tabType == common::TabType::APPLY_FOR_TAB) {
                    common::Tools::getInstance()->getLogger()->trace("{0} {1} loadWindowMiddle APPLY_FOR_TAB", __FILE__, __LINE__);
                    TODO("请求后端查询该用户的添加好友列表记录(就是获取 json 数据)");
                    TODO("可以做时间戳优化");
                    TODO("根据 json 制作列表 addFriendListOfUser_");
                    /*
                    for (auto addFriend : addFriendListOfUser_) {
                        sessionFriendAreaInWindowMiddle->addItem(...);
                    }
                    */
                    for (int i = 0; i < 20; i++) {
                        sessionFriendAreaInWindowMiddle->addItem(
                            common::SessionFriendItemType::APPLY_FOR_ITEM_TYPE,
                            QString::number(i),
                            QIcon(":/test/xingmou.png"),
                            "xingmou",
                            "Hello, I am xingmou!"
                        );
                    }
                }
                else {
                    common::Tools::getInstance()->getLogger()->error("{0} {1} Unknown TabType", __FILE__, __LINE__);
                }
            });

            // 当 windowMiddle_ 发送重加载信号后, windowRight_ 重新加载列表
            connect(windowMiddle_, &window::WindowMiddle::loadWindowRight, this, [this](const QString& chatSessionId){
                common::Tools::getInstance()->getLogger()->trace("{0} {1} get loadWindowRight signal", __FILE__, __LINE__);

                windowRight_->switchShow(false); // 去除背景 logo
                windowRight_->getMessageShowArea()->cleanAllTextMessageBubble(); // 清理气泡

                // TODO: 根据 chatSessionId 的值请求后端查询该会话的聊天记录
                auto user2 = model::UserModel::makeUser(
                        "Limou",
                        "123456",
                        "Coding...",
                        QIcon(":/test/limou.png")
                );
                auto message2 = model::MessageModel::makeMessage(
                        "1",
                        common::MessageType::TEXT_TYPE,
                        user2,
                        QString("Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!").toUtf8()
                );
                windowRight_->getMessageShowArea()->addTailTextMessageBubble(true, message2);

                auto user3 = model::UserModel::makeUser(
                        "Limou",
                        "123456",
                        "Coding...",
                        QIcon(":/test/limou.png")
                );
                auto message3 = model::MessageModel::makeMessage(
                        "1",
                        common::MessageType::TEXT_TYPE,
                        user3,
                        QString("Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!").toUtf8()
                );
                windowRight_->getMessageShowArea()->addFrontTextMessageBubble(false, message3);
            });
        }

        // 设置组件显示方法
        void setElementShow() {
            windowLeft_->hide();
            windowMiddle_->hide();
            windowRight_->hide();

            // 验证用户凭证
            auto loginWig = new window::UserLogin();
            loginWig->show();

            TODO("阻塞, 用户填入信息后, 并向服务端请求验证, 登录成功后, 保存用户密钥, 允许进入主界面开始访问");

            bool loginIsSucceed = true;
            if (loginIsSucceed) {
                TODO("允许进入主界面开始访问");
                windowLeft_->show();
                windowMiddle_->show();
                windowRight_->show();
            }
            else {
                TODO("不允许进入主界面开始访问");
                TODO("显示登录失败弹窗");
            }

            // 模拟用户一次点击, 提前显示出列表内容(符合用户直觉)
            windowLeft_->onButtonClicked(common::TabType::SESSION_TAB); // 加载会话列表, 方便用户快速选择会话项
        }
    };
    // <<< class MainQWidget end <<<
} // namespace chat_system end

#endif // FRONTEND_MAINQWIDGET_HPP


